//
//  AirportDetailViewModel.swift
//  CitySearch
//
//  Created by guotonglin on 2020/6/9.
//  Copyright © 2020 guotonglin. All rights reserved.
//

import Foundation
import RxCocoa
import RxSwift

protocol AirportDetailViewPresentable {
    
    typealias Output = (
        airportDetail: Driver<AirportViewPresentable>,
        mapDetails: Driver<AirportMapViewPresentable>
    )
    
    typealias Input = ()
    
    typealias Dependencies = (model: AirportModel, currentLocation: Observable<(lat: Double, lon: Double)?>)
    
    typealias ViewModelBuilder = (AirportDetailViewPresentable.Input) -> AirportDetailViewPresentable
    
    var input: AirportDetailViewPresentable.Input { get }
    var output: AirportDetailViewPresentable.Output { get }
}


struct AirportDetailViewModel: AirportDetailViewPresentable {
    
    var input: AirportDetailViewPresentable.Input
    var output: AirportDetailViewPresentable.Output

    private let bag:DisposeBag = DisposeBag()
    
    typealias RouterAction = (airportSelectedRelay: PublishRelay<AirportModel>, ())
    
    private let routerAction: RouterAction = (PublishRelay(), ())
    
    typealias Routing = (citySelected: Driver<AirportModel>, ())
    
    lazy var router: Routing = (citySelected: routerAction.airportSelectedRelay.asDriver(onErrorDriveWith: .empty()), ())
    
    init(input: AirportDetailViewPresentable.Input, dependencies: AirportDetailViewPresentable.Dependencies) {
        self.input = input
        self.output = AirportDetailViewModel.output(input: input, dependencies: dependencies)
        self.process(dependencies: dependencies)
    }
}

private extension AirportDetailViewModel {

    static func output(input: AirportDetailViewPresentable.Input, dependencies: AirportDetailViewPresentable.Dependencies) -> AirportDetailViewPresentable.Output {
        
        let airportDetails: Driver<AirportViewPresentable> = dependencies.currentLocation
            .filter({ $0 != nil })
            .map({ $0! })
            .map({[model = dependencies.model] in
                AirportViewModel(usingModel: model, currentLocation: $0)
            })
            .asDriver(onErrorDriveWith: .empty())
        
        
        let mapDetails: Driver<AirportMapViewPresentable> = dependencies.currentLocation
            .filter({ $0 != nil })
            .map({ $0! })
            .map({[airportModel = dependencies.model] (currentLocation) in
                guard
                    let lat = Double(airportModel.lat),
                    let lon = Double(airportModel.lon) else {
                        throw CustomError.error(messae: "Airport location error")
                }
                let airportLocation = (lat: lat, lon: lon)
                return AirportMapViewModel(airport: (name: airportModel.name, city: airportModel.city), currentLocation: currentLocation, airportLocation: airportLocation)
            })
            .asDriver(onErrorDriveWith: .empty())
        
        return (
            airportDetail: airportDetails,
            mapDetails: mapDetails
        )
    }
    
    func process(dependencies: AirportDetailViewPresentable.Dependencies) {
        
    }
}
